\section{Introduction}

Ce document accompagne le prototype XWiki Concerto L4. Il décrit le contenu du prototype et il explique la mise en oeuvre de XWoot et de la skin iPhone XWiki Concerto.


\section{Prototype}

Le prototype L4 est livré sous la forme d'un fichier compressé \texttt{XWikiConcerto.L4.prototype} contenant les dossiers suivants:

\begin{itemize}
\item \textt{xwikiconcerto-xwoot}: contient un fichier d'installation \texttt{XWoot-installer.jar} qui doit être lancé avec un runtime Java 1.5. Il s'agit d'une installation d'un peer XWiki Concerto avec les modules de réplication P2P XWoot. Ce répertoire contient également les fichiers source de l'application.
\item \textt{xwikiconcerto-iphone}: contient les fichiers adaptant l'interface XWiki aux terminaux iPhone.
\item \textt{xwikiconcerto-eclipse}: contient le client riche XWiki Eclipse permettant un travail en mode déconnecté par intermittence. Quatre versions sont disponibles en ligne~\footnote{\url{http://code.xwiki.org/xwiki/bin/view/Extensions/XEclipseExtension}}, pour les quatre système d'exploitation suivants: Apple MacOSX PPC, Apple Mac OS X86, Linux et Windows. 
\end{itemize}

\section{XWoot}

\begin{figure}
  \centering
  \includegraphics[width=0.5\textwidth]{figures/xwootlogo.jpg}
  \caption{XWoot - logo}
  \label{fig:xwoot-logo}
\end{figure}


Cette section accompagne le livrable de spécification XWiki Concerto L5 et a été rédigée par Julien Maire, Pascal Molli et Gérôme Canals (INRIA). Elle comporte les sous-sections suivantes:
\begin{itemize}
\item introduction replaçant le livrable dans le contexte du projet,
\item documentation à destination des utilisateurs,
\item documentation de développement pour l'ensemble des composants du prototype.
\end{itemize}

\subsection{Introduction}

L'application XWoot est le prototype XWiki Concerto V1. Ce prototype implante des services P2P de base pour la dissémination de patchs sur un réseau P2P ainsi qu'un service de réconciliation de données basés sur l'algorithme Woot.

Cette implantation est basée sur l'architecture et les spécifications fournies dans le livrable L2-2, août 2007, section 2.4.1.2. Elle se base donc sur :

\begin{itemize}
\item l'algorithme WOOT (WithOut Operational Transformation) pour la synchronisation des données textuelles (contenu des pages),
\item l'algorithme LPBCast~\footnote{\url{http://portal.acm.org/citation.cfm?id=945507&jmp=abstract&coll=portal&dl=ACM}} pour la propagation des messages entre les différents noeuds du réseau.
\item la librairie JLibDiff~\footnote{\url{http://potiron.loria.fr/projects/jlibdiff}} développée par l'équipe ECOO~\footnote{\url{http://www.inria.net/recherche/equipes/ecoo.en.html}} du LORIA pour le calcul des différences entre deux contenus,
\item l'utilisation d'une règle de Thomas (ThomasRuleEngine~\footnote{\url{http://tools.ietf.org/html/rfc677}}) pour la synchronisation des méta-données XWiki (attributs attachés aux pages).
\end{itemize}

XWoot est une application indépendante de XWiki qui a pour fonction principale la réplication de pages wiki sur un réseau P2P.
Dans sa version actuelle, l'accès à XWiki n'est réalisé que pour des raisons de test et de démonstration. Cette connexion est réalisée à travers l'interface XML-RPC de XWiki. Cette interface est trés limitante puisqu'elle permet seulement 
\begin{itemize}
\item d'accéder au contenu courant d'une page et de quelques méta-données,
\item de positionner le contenu d'une page et de quelques méta-données.
\end{itemize}

Cette interface impose donc à l'application XWoot :

\begin{itemize}
\item des limitations sur la réplication et la synchronisation des méta-données : toutes ne sont pas traitées,
\item de calculer elle même les patchs correspondant aux changements de contenu des pages, 
\item de systématiquement et régulièrement accéder au contenu des toutes les pages pour détecter les éventuels changement.
\end{itemize}

Le dernier point pénalise particulièrement les performances de l'application. 

La prochaine version de XWoot sera connectée à XWiki de manière plus efficace, c'est à dire en utilisant l'interface de publication de patchs qui doit venir étendre XWiki. L'utilisation de cette interface résoudra les limitations citées ci-dessus.




\subsection{Documentation utilisateur}

\subsubsection{Fichier war}

L'application compilée se présente sous la forme [d'un fichier "Web Archive" (WAR)>getit!], qui peut être déployé dans un container de Servlet (Ex recommandé : Tomcat).

Les sources de l'application sont disponibles sur le repository Subversion d'XWiki. Le projet est sous Maven2 (se reporter à la documentation développeur pour plus de détail).

\subsubsection{Configuration}

Une fois l'application Web déployée par le container de Servlet (i.e. création du dossier de même nom), il faut compléter deux fichiers de propriétés avec les valeurs appropriées. Ces fichiers se trouvent à la base du répertoire déployé (xwiki.properties et xwoot.properties).

\paragraph{xwiki.properties}

\begin{itemize}
\item xwiki.server : adresse de base du serveur XWiki auquel se connecter (ex : citrouille.loria.fr/xwiki)
\item xwiki.username : username utilisé pour la connexion à XWiki (ex : Admin -- les tests n'ont été effectués qu'avec le login de l'administrateur)
\item xwiki.password : password de l'utilisateur
\item xwiki.space : espace par défaut (exemple : Main)
\item xwiki.pageid : page par défaut (exemple : WebHome)
\end{itemize}

\paragraph{xwoot.properties}

\begin{itemize}
\item xwoot.working.dir : dossier dans lequel sont stockés les objets sérialisés (dossier de travail de l'application : il doit exister et être accessible en lecture/écriture -- ex :  /tmp/xwoot)
\item xwoot.site.id : identificateur unique du noeud (l'adresse IP peut faire l'affaire si elle ne dépasse pas 2147483648, car la valeur est stockée dans un entier ex : 152811181 )
\item xwoot.server.url : url de déploiement de l'application xwoot. Il est conseillé de ne pas utiliser localhost (faire un alias local de la forme "http://alias.fr/xwoot" ou utiliser un DNS) -- ex : http://concerto.loria:8080/xwoot)
\item xwoot.server.name : inutile mais doit être renseigner (laisser la valeur par défaut)
\item xwoot.refresh.log.delay : inutile mais doit être renseigner (laisser la valeur par défaut)
\item xwoot.neighbors.list.size : nombre maximal de voisins dans la table
\item xwoot.pbcast.round : nombre de rebond de chaque message (mettre le même nombre que celui de voisins)
\end{itemize}

\paragraph{Première exécution}

Taper l'adresse de déploiement de l'application dans un navigateur Web. La servlet de bootstrap doit alors initialiser l'application et afficher la page principal de configuration de XWoot. Si un problème se pose par rapport aux données des fichiers de propriété, un message s'affiche.

\paragraph{Présentation de l’interface}

L'interface principale permet (de haut en bas) :
\begin{itemize}
\item d'ajouter l'ensemble des pages du Wiki aux pages à synchroniser
\item d'accéder à un menu de sélection manuelle des pages à synchroniser
\item de supprimer toutes les pages ajoutées dans les pages à synchroniser
\item de lancer une synchronisation
\item de voir une liste des voisins (avec pour chaque voisin la possibilité de le supprimer, de lancer un échange d'état ou une anti-entropie)
\item de voir une liste des pages à synchroniser
\end{itemize}

\subsection{Remarques}

Du fait du mode d'interaction avec le serveur XWiki (interface XML-RPC), ce prototype fonctionne pour un nombre restreint de pages (ce nombre est fonction de la taille du contenu des pages). Un début de solution est aussi appliqué aux méta-données. La gestion des patchs transférée à l'application XWiki allègera considérablement l'application de réplication et permettra de résoudre les différents problèmes rencontrés.

\subsection{Documentation développeur}

\subsubsection{Installation}

\paragraph{Sources}

Les sources du projet s'articulent dans le format Maven2. L'ensemble des sources est en Java 1.5 et est disponible depuis le répertoire de sources XWiki.

\paragraph{Maven2}

Le projet XWoot est un projet Maven2 multi-module~\footnote{\url{http://maven.apache.org/guides/getting-started/index.html}}: à chaque composant de l'application correspond un module :


\begin{itemize}
\item ClockEngine
\item WootEngine
\item ThomasRuleEngine
\item WikiContentManager
\item LPBCast
\item AntiEntropy
\item XWootApp
\end{itemize}

A la base du répertoire des sources se trouve le fichier pom principal de l'application ; il fait référence à chaque module dont il dépend. Dans chaque dossier de chaque module, se trouve un fichier pom.xml correspondant au composant. Ainsi, chaque composant peut être compilé séparément. Si la compilation réussie, un dossier target contenant le résultat de la compilation se met à jour (fichier jar ou war ...).

L'application XWoot correspond au module XWootApp ;  c'est donc en compilant ce module que l'on peut obtenir le fichier war à déployer. Il est cependant préférable de compiler directement depuis le fichier pom principal (à la base du répertoire des sources), qui lui va compiler chacun des modules.

Les plugins maven2 utilisés sont :

\begin{itemize}
\item Jalopy : formatage standard du code
\item Junit
\item Javadoc
\end{itemize}

\subsubsection{Environnement de développement}

L'ensemble du code a été développé sous l'environnement de développement Eclipse, auquel peuvent être ajoutés les plugins suivants:

\begin{itemize}
\item Gestion de Tomcat : Sysdeo Eclipse Tomcat Launcher plugin~\footnote{\url{http://www.eclipsetotale.com/tomcatPlugin.html}}
\item Gestion  SVN : Subclipse~\footnote{\url{http://subclipse.tigris.org/}}
\item Gestion Maven2 : Maven Integration for Eclipse~\footnote{\url{http://m2eclipse.codehaus.org/}}
\end{itemize}

L'application a été principalement testée avec Firefox en environnement Linux.

\subsubsection{Container de servlet}

Pour déployer le fichier war, il est nécessaire d'utiliser un container de Servlet. Pour l'ensemble du développement, le container Tomcat a été utilisé.

\subsubsection{Tests}

Il est recommandé de lire les tests pour s'approprier plus facilement le code.

L'ensemble des tests a été réalisé avec Junit 4.4~\footnote{\url{http://www.junit.org/}}.

Les principaux composants utilisés par l'application XWoot possèdent un ensemble de tests JUnit. L'utilisation de Maven2 simplifie leurs exécutions ("mvn test" en ligne de commande dans le dossier du composant à tester, ou dans le dossier principal de l'application pour lancer l'ensemble des tests ; "run as mvn test" avec le plugin maven2 de Eclipse).

\subsubsection{Log}

La bibliothèque Log4J~\footnote{\url{http://logging.apache.org/log4j/}} est utilisée dans les composants principaux pour logger le déroulement des opérations durant l'exécution.

\subsubsection{Javadoc}

Les classes principales de chaque composants ont une JavaDoc complétée. Celle-ci peut être facilement générée en utilisant Maven2.


\subsection{Architecture de l'application}


\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{figures/archi_xwoot_proto_mars.jpg}
  \caption{Diagramme de composant de l'application XWoot}
  \label{fig:xwoot-arch}
\end{figure}


\subsubsection{Clock engine}

\paragraph{Service fourni}

Composant simple de génération d'une clock. L’algorithme de Woot nécessite la génération d’un identificateur unique au site. En effet, chaque opération Woot possède un identificateur composé en partie d’une clock (valeur incrémentée à chaque nouvelle opération). De plus, chaque patch généré par un site possède aussi une clock. Le module clockEngine permet de fournir ce service.

\paragraph{Serialisation}

Le module ClockEngine sérialise les données dans des fichiers. A chaque appel/modification de la clock, l’utilisateur doit charger les données en pré-condition et sauvegarder les données en post-condition.

\paragraph{Diagramme de composant}


\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{figures/ClockEngineComponent.jpg}
  \caption{Diagramme de composant Clock engine}
  \label{fig:clockengine}
\end{figure}


\paragraph{Entrée}

Méthode set : permet d’incrémenter la clock .

\paragraph{Sortie}

Méthode get : permet de récupérer l’état courant de la clock.

\paragraph{Diagramme de classe}


\begin{figure}
  \centering
  \includegraphics[width=0.5\textwidth]{figures/ClockEngine_class2.jpg}
  \caption{Diagramme de classe du composant Clock engine}
  \label{fig:clockengine-class}
\end{figure}


\subsubsection{Woot engine}

\paragraph{Intégration de données linéaires dans un contexte P2P}

Le composant WootEngine permet d’intégrer des données linéaires, dans un contexte collaboratif (entre différents composants WootEngine) de façon répliquée. Ce composant assure la convergence des données entre différents sites, sans site central, sans consensus distribué, sans ordre total, ni vecteur d’état. Il doit se plugger à XWiki, qui lui fourni les modifications effectuées sur ses données ; à partir des modifications, le composant WootEngine génère un modèle interne (qu'il maintient en fonction des modifications locales ou distantes). Le composant WootEngine est basé sur l'algorithme Woot.

\paragraph{Un composant par nœud}

Chaque application voulant synchroniser ses données avec le réseau collaboratif, doit utiliser un composant WootEngine pour pouvoir se synchroniser et intégrer les données.

\paragraph{Différentiation modèle / vue}

Le composant WootEngine utilise un modèle interne représentant l'ensemble des données partagées. Ainsi, on appelle la vue, les données visibles par l'utilisateur à travers l'application d'édition (i.e. XWiki), et le modèle, ces mêmes données "transformées" par le composant WootEngine.

\paragraph{Utlisation d'un modèle d’opération}

Le composant WootEngine utilise un ensemble d'opérations Woot pour assurer la convergence des données et maintenir son modèle interne. A chaque modification d’une page du site local, sont générées des opérations Woot, qui sont intégrées localement, puis fournies sous forme de patch Woot. Ce patch peut alors être envoyé à d’autres sites pour intégrer les modifications correspondantes.

\paragraph{Intégration d'opération ou de patch}

Il existe deux types de modifications : les modifications locales, effectuées par les utilisateurs de l'application locale (i.e. l'application pluggée au composant WootEngine), et les modifications distantes, effectuées par les utilisateurs des applications connectées au réseau collaboratif. Lors de chaque modification locale, est généré un patch Woot contenant l'ensemble des opérations Woot correspondantes ; ce patch est ensuite fourni par le composant WootEngine pour qu'il soit transmis aux autres noeuds du réseau. Chaque nœud reçoit alors un patch Woot qu'il intègre localement à travers le composant WootEngine associé au noeud.

\paragraph{Interrogation du modèle interne}

Chaque site doit régulièrement synchroniser sa vue avec le modèle du composant WootEngine. Pour ce faire, le composant fournit un ensemble de méthode permettant d'accéder (de manière lisible par l'application) au modèle.

\paragraph{Echange d'état}

Le composant WootEngine permet aussi d’agir directement sur l’état du modèle. Ainsi, par l’intermédiaire d’un getter/setter, on peut récupérer/remplacer le modèle interne courant. Cette fonction peut être utilisée pour mettre à jour un composant WootEngine dont le modèle est vierge, en le remplaçant par celui d’un composant dont le modèle est à jour (i.e. échange d’état).

\paragraph{Serialisation du modèle interne}

L'ensemble des pages stockées dans le modèle interne sont sérialisées dans des fichiers.

\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{figures/WootEngineComponent.jpg}
  \caption{Woot engine}
  \label{fig:wootengin}
\end{figure}



\paragraph{Entrées du composant}

\begin{itemize}
\item Méthode ins : insertion d’une donnée dans une page à une position absolue.
\item Méthode del : supression d’une unité atomique à une position absolue.
\item Méthode deliverPatch : application des opérations contenues dans un patch.
\item Méthode setState : remplacement de l’état courant du modèle par un état donnée.
\end{itemize}

\paragraph{Sorties du composant}

\begin{itemize}
\item Méthodes ins/del : la méthode renvoie l’opération au format Woot correspondant à l’insertion effectuée.
\item Méthode getPage : récupération d’une page données au format String.
\item Méthode createPatch : création d’un patch à partir d’un vecteur d’opérations Woot.
\item Méthode getState : récupération de l’état courant du modèle interne (Zip des fichiers de sérialisation des données).
\end{itemize}

\paragraph{Diagramme de classes}

La figure~\ref{fig:wootengine-class} représente le diagramme de classes du composant Woot engine.

\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{figures/WootEngine_class.jpg}
  \caption{Diagramme de classe du composant Woot engine}
  \label{fig:wootengine-class}
\end{figure}

\subsubsection{Thomas rule engine}

\paragraph{Les métadonnées}

XWiki possède un ensemble de métadonnées associées à chaque page, commentaire ou encore pièce jointe. On trouvera par exemple associé à chaque page:

\begin{itemize}
\item Id (String) : identificateur unique de la page
\item Space (String) : identificateur de l’espace de la page
\item Title (String) : titre de la page
\item Created (Date) : date de création de la page
\item Creator (String) : login du créateur de la page
\item Modified (Date) : date de création de la page
\item Modifier (String) : login du dernier utilisateur ayant modifié la page
\item Content (String) : contenu de la page (cette donnée est traitée par le WootEngine)
\item Version (int) : version de la page
\item homePage (boolean) : la page est elle homePage de l'espace
\end{itemize}

\paragraph{Difficulté de fusion des métadonnées}

Il n'est pas possible de fusionner et de résoudre des conflits de métadonnées avec le moteur du WootEngine (les métadonnées sont représentées sous forme d’XML ; le WootEngine permet de gérer des structure linéaires et non arborescentes…).

\paragraph{La règle du Last Writter Win (LWW)}

Afin de remédier au problème des métadonnées, nous avons choisi d’utiliser la règle de Thomas~\footnote{\url{http://tools.ietf.org/html/rfc677}}. Plus communément appelé la règle du Last Writter Win (LWW), cet algorithme représente un compromis permettant de faire converger la réplication des métadonnées vers un état commun.

\paragraph{Modèle de représentation des métadonnées}

Ce composant permet de stocker les métadonnées en appliquant directement l’algorithme du LWW. Pour ce faire il utilise un modèle interne permettant de générer/d’appliquer des opérations correspondantes aux modifications des métadonnées effectuées dans XWiki.

\paragraph{Application d’opérations}

A chaque opération effectuée dans XWiki sur des métadonnées, le composant ThomasRuleEngine va être sollicité pour récupérer l’opération ThomasRuleEngine correspondante. Celle-ci sera appliquée localement et envoyée aux autres sites. Lorsqu’un site reçoit une opération, il l’applique à son modèle ThomasRuleEngine ; la règle du LWW sera alors appliquée : l’opération sera exécutée en fonction des conditions de l’algorithme.

\paragraph{Serialisation du modèle interne}

L'ensemble des métadonnées stockées dans le modèle interne sont sérialisées dans des fichiers.

\paragraph{Modèle interne}

Une donnée lorsqu'elle est supprimée ne l'est pas physiquement, c'est un attribut booléen (Tombstone) qui caractérise sont existence.

Chaque donnée est représentée par deux éléments devant être fournis par le client du composant voulant
gérer une nouvelle métadonnée: un identifiant unique, une valeur donnée.

De plus, trois éléments sont attribués automatiquement par le composant lors de la
création d’une nouvelle entrée (i.e. : demande d’opération par le
client du composant) :

\begin{itemize}
\item Une « tombstone » : un booléen à True si la donnée est supprimée, à False sinon.
\item Un premier « timestamp » : date de création de la donnée.
\item Un second « timestamp » : date de modification de la donnée.
\end{itemize}

L’ensemble de ces cinq élément correspond à un objet de type Entry.

Le module ThomasRuleEngine doit gérer un objet de
type EntriesList, contenant l’ensemble des données traitées. La
sérialisation concerne cet objet. Chaque accès à cet objet nécessite de
le charger en pré-condition et de le sauvegarder en post-condition.

\paragraph{Les opérations}

Il existe trois types d’opérations :

\begin{itemize}
\item La création (ThomasRuleOpNew)
\item L’édition (ThomasRuleOpSet)
\item La suppression (ThomasRuleOpDel)
\end{itemize}

Ces trois opérations héritent de la classe abstraite ThomasRuleOp.


\paragraph{Algorithme de création d'une nouvelle opération}

Condition de création d’une nouvelle opération en fonction d’un identificateur, d’une valeur et d’un module ThomasRuleEngine :

\begin{verbatim}
Soit  	id : identificateur ;
	val : valeur ;
	tre : ThomasRuleEngine ;
	e : tre.get(id) ;

	Si (val !=null && (e==null || e.isDeleted())
	return new ThomasRuleOpNew ;

Sinon
	Si (e!=null)
		Si (val!=null && !e.isDeleted())
			Si (!val.equals(e.getValue())
				return new ThomasRuleOpSet ;
			FinSi
		Sinon
			return new ThomasRuleOpDel ;
		FinSi
	FinSi
FinSi

return null ;
\end{verbatim}

\paragraph{Vérification des timestamps}

Une opération donnée est appliquée si ses timestamps vérifient certaines conditions :

\begin{verbatim}
Soit  	op : ThomasRuleOp ;
	tre : ThomasRuleEngine ;
	e : tre.get(op.getIdentificateur()) ;
	
Si (e !=null)
	Si (e.getTimestampCreation > op.getTimestampCreation)
		return false ;

	Sinon
		Si (e.getTimestampCreation == op.getTimestampCreation)
			Si (e.getTimestampModif >= op.getTimestampModif)
				return false;
			FinSi
		FinSi
	FinSi
FinSi
return true;
\end{verbatim}

Condition particulière :

Pour les opérations d’édition et de suppression,
si l’identificateur donné n’existe pas dans le modèle interne,
l’opération est précédée d’une opération de création.

\paragraph{Diagramme de composant}


\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{figures/ThomasRuleEngineComponent.jpg}
  \caption{Composant Thomas rule engine}
  \label{fig:thomasrule}
\end{figure}


\paragraph{Entrées}

\begin{itemize}
\item getOp : permet de créer un object représentant l’opération ThomasRuleEngine correspondant au couple identificateur/valeur fourni.
\item getValue : permet de récupérer la valeur associée à un identificateur donné dans le modèle interne.
\end{itemize}

\paragraph{Sortie}

\begin{itemize}
\item applyOp : permet d’appliquer au modèle interne une opération ThomasRuleEngine donnée.
\end{itemize}

\paragraph{Diagramme de classe}


\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{figures/TRE_class.jpg}
  \caption{Diagramme de classe du composant Thomas rule engine}
  \label{fig:thomasrule-class}
\end{figure}


\subsubsection{WikiContentManager}

\paragraph{Interface XWiki / XWoot}

Le module WikiContentManager permet l’échange de données entre l'application XWoot et l’application XWiki. Il s’occupe de la gestion des interfaces fournies par l’application XWiki. A travers une classe interface, il permet de rendre transparent à l'application XWoot, la gestion de l'accès aux données de l'application XWIki.

\paragraph{Deux interfaces XML-RPC}

Le module WikiContentManager utilise deux connections proposées par l’application XWiki ; en fonction du constructeur utilisé, le service rendu utilise soit une interface XML-RPC de base (sans gestion des métadonnées), soit une interface XML-RPC typée : [SWIZZLE>http://swizzle.codehaus.org/Swizzle+Confluence].
Il est d’ailleurs conseillé d’utiliser la seconde qui est plus aboutie.

\paragraph{Diagramme de composant}


\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{figures/WikiContentManagerComponent.jpg}
  \caption{Diagramme de classe du composant WikiContentManager}
  \label{fig:wcm}
\end{figure}

\paragraph{Entrées}


\begin{itemize}
\item Méthode createPage : permet de créer une nouvelle page vide dans un espace donné
\item Méthode setPageContent : permet de mettre à jour le contenu d’une page (il existe deux méthodes pour ce faire ; une première qui écrase le contenu existant et une seconde qui ne met à jour que si le md5 de la page de l’application XWiki est le même que celui fourni en paramètre correspondant à la dernière page vue par XWoot)
\item Méthode setFields : permet d’enregistrer les métadonnées d’une page.
\item Méthode removePage : permet de supprimer une page au niveau de l’application XWiki.
\item Méthode setComment : permet d’enregistrer un commentaire au niveau de l’application XWiki.
\end{itemize}

\paragraph{Sorties}

- Méthodes d’accès aux différentes données (espaces, pages, commentaires, métadonnées…)

\paragraph{Diagramme de classe}


\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{figures/WCM_class2.jpg}
  \caption{Diagramme de classe du composant WikiConctentManager}
  \label{fig:wcm-class}
\end{figure}


\subsubsection{LPBCast}

\paragraph{Algorithme probabiliste de diffusion de message}

Ce module est une implémentation (non complète) de l’algorithme LPBCast (Lightweight Probabilistic broadcast)~\footnote{\url{http://portal.acm.org/citation.cfm?id=945507&jmp=abstract&coll=portal&dl=ACM}}. Cet algorithme permet de diffuser de manière probabiliste des messages entre différents nœuds d’un réseau P2P. Ainsi, il est prouvé que chaque nœud connecté recevra chaque message envoyé en un temps donné.

\paragraph{Gestion des voisins}

Le composant LPBCast possède une table des voisins de taille fixe (chaque voisin est représenté par l'url de l'application XWoot cliente du composant LPBCast) ; elle représente donc une vue partielle du réseau. Le module intègre, dans chaque message envoyé, la configuration d’un voisin pris aléatoirement dans sa table. Ainsi, chaque nœud recevant ce message met à jour sa table avec ce voisin (ajout si taille maximale non atteinte, remplacement aléatoire sinon).

\paragraph{Gestion des messages}

Chaque message envoyé contient un attribut « round ». Cet attribut est initialisé lors de la création du nouveau message, par une valeur donnée en configuration. Lorsqu’un message est reçu par un nœud, il est traité, puis diffusé aux voisins de ce nœud. Cependant, avant la diffusion, le nœud décrémente la valeur du « round » ; dès que celle-ci arrive à 0, le message n’est plus envoyé.

\paragraph{Différents types de message}

Chaque message contient un attribut permettant de connaitre son type. Il existe trois types de messages ; ils peuvent transmettre des patchs, mais aussi correspondre à une demande plus spécifique (Anti-entropie, échange d'état).

\paragraph{Le transfert d’état}

Le module LPBCast permet aussi de transférer un état d’un nœud à un autre. Lorsqu’un nouveau nœud se connecte au réseau (uniquement au « bootstrap » (i.e. première connexion au réseau : ce qui suppose que le nœud ne contient pas encore de donnée)), il demande à un nœud de sa table de voisin son état ; il récupère alors l’ensemble des données de son voisin. Ce transfert est ensuite complété avec une anti-entropie.

\paragraph{Servlets}

L'ensemble des communication entre les nœuds (envoi de message, échange d'état) ce fait par appel de Servlet (i.e.http).

\paragraph{Diagramme de composant}


\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{figures/LPBCastComponent.jpg}
  \caption{Diagramme du composant LPBCast}
  \label{fig:lpb}
\end{figure}


\paragraph{Entrées (receiver)}

\begin{itemize}
\item receive : méthode à implémenter permettant de recevoir un objet en tant que nœud dans le réseau. Tout entité voulant être un nœud dans le réseau, doit implanté l'interface receiver.
\end{itemize}

\paragraph{Sortie (sender)}

\begin{itemize}
\item getNeighbors : permet d’obtenir la liste des voisins du nœud
\item sendTo : permet d’envoyer un message à un voisin
\item getNewMessage : permet la création d’un objet de type message en fonction d’un type, d’un round et d’en contenu
\item gossip : permet d’appliquer et de rediffuser un message
\item askState : permet d’envoyer un message à un voisin de la table demandant un transfert d’état.
\end{itemize}

\paragraph{Diagramme de classe}


\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{figures/LPBCast_class2.jpg}
  \caption{Diagramme de classe du composant LPBCast}
  \label{fig:lpb-class}
\end{figure}


\subsubsection{XWootApp}

\paragraph{Objectifs}

L'application XWoot à pour objectif l'ajout d'une fonction de réplication de données par P2P à l'application XWiki, dans un contexte d'édition collaborative. En effet, l'association des deux applications XWoot / XWiki permet de faire évoluer chaque serveur XWiki en un nœud d'un réseau P2P de travail collaboratif. Chaque nœud peut alors synchroniser ses données à travers le réseau, afin de partager un contenu commun répliqué. L'algorithme utilisé (WOOT) garanti la convergence des différents répliquas vers un état identique.

Pour ce faire, XWoot utilise l'interface XML-RPC Swizzle fournie par XWiki, afin d'agir sur les données à répliquer.

Encore au stade de prototype, il est déjà possible de répliquer le contenu des pages, ainsi qu'une partie des métadonnées liées.

L'application se présente sous la forme d'un fichier WAR (Web Archive) contenant une application Web à déployer à l'aide d'un conteneur de Servlet (Ex : Tomcat). Elle doit être configurée par le biais de 2 fichiers de propriétés (par exemple, il faut fournir l'adresse d'accès à l'interface XML-RPC de l'application XWiki à laquelle on veut se connecter).

\paragraph{Architecture à composants}

L'application XWoot est basé sur le composant XWootApp, lui même client de plusieurs composants :

\begin{itemize}
\item WikiContentManager: composant d'accès au données de l'éditeur wiki (XWiki)
\item WootEngine: composant d'intégration de données linéaire, répliquées dans un contexte d'édition collaborative.
\item ClockEngine: composant fournissant un compteur persistant.
\item JLibDiff: librairie utilisée pour générer la différence entre deux contenus.
\item ThomasRuleEngine: composant d'intégration de métadonnées utilisant la règle du "First Writter Win".
\item LPBCast: composant de gestion du réseau P2P (implémente l'algorithme Lightweight Probabilistic broadcast).
\item AntiEntropy: composant de gestion de l'anti-entropie.
\end{itemize}

\paragraph{Le composant XWootApp}

Le composant XWootApp intègre l'application Web, permettant de gérer l'application, à travers plusieurs servlets :
\begin{itemize}
\item Bootstrap : servlet de démarrage de l'application, charge les propriétés et met en place les différentes instances des composants.
\item Synchronize : servlet de gestion de la synchronisation des données entre la vue et le modèle.
\item PageManagement : servlet de gestion du choix des pages à synchroniser.
\item ReceiveMessage : servlet utilisé par le module LPBCast pour recevoir les messages des voisins.
\item GetState : servlet utilisé par le module LPBCast pour charger le modèle interne d'un voisin lors du bootstrap.
\end{itemize}

Dans la version actuelle du prototype, le composant XWootApp fourni un service de gestion des pages à synchroniser ; à terme, il faudra synchroniser l'ensemble des pages du Wiki, car c'est une condition pour rendre effective la convergence des données répliquée. Ainsi, il est possible d'accéder à une liste des espaces et de leurs pages, permettant de choisir celles que l'on souhaite répliquer.

L'interface Web permet aussi d'ajouter les voisins du nœud, ainsi que de lancer une synchronisation entre le wiki et le modèle de données. A terme, un seul voisin suffira pour le bootstrap et la synchronisation des données se fera soit par demande de l'application Wiki, soit par l'intermédiaire d'un scheduler.

Ces différentes interfaces Web sont donc vouées à disparaitre, pour être remplacées par une gestion avancée des fichiers de propriétés.

\paragraph{La synchronisation des données}

L'application XWoot, à travers le composant WootEngine, crée un modèle des données répliquées ; c'est pourquoi, il est nécessaire de garder synchronisées les données de la vue, avec celles du modèle interne au WootEngine. Le modèle interne du WootEngine permet de recevoir les patchs dans un ordre aléatoire, en revanche, il faut modifier la vue en tenant compte de toutes les modifications (locales et distantes) sans écrasement.

Le composant XWootApp fourni donc un service de synchronisation qui va, pour chaque page sélectionnée pour la synchronisation, vérifier si les données n'ont pas été modifiées soit par des utilisateurs locaux de l'interface Wiki, soit par la réception et l'application au modèle de patchs distants.

\paragraph{Le problème de la synchronisation vue/modèle}

Lorsque le modèle interne du WootEngine est modifié par l'application de patchs (modifications faites par des utilisateurs sur des applications distantes), le composant XWootApp doit pouvoir mettre à jour les données de la vue (i.e. contenues par l'application XWiki locale) sans écraser d'éventuels modifications (i.e. faites sur la vue) n'ayant pas encore été prises en compte par le WootEngine (i.e. le modèle).  Pour ce faire, le composant XWootApp doit garder une copie de l'état de la vue tel qu'il était lors de la dernière synchronisation. Ainsi, lorsque le composant XWootApp veut modifier la vue, il doit vérifier que l'état courant de la vue est bien le même que l'état copié lors de la dernière synchronisation.

La solution proposée n'est d'ailleurs pas parfaite, puisque l'application XWoot étant externe à l'application XWiki, il est impossible de rendre atomique la zone critique de vérification de l'état courant de la vue ; il existe donc un risque mineur de modification de la vue à la suite de la vérification mais avant l'écrasement des données (cette modification ne serait alors pas prise en compte).

\paragraph{La synchronisation des métadonnées}

Cette fonction est en cours de développement et n'est pas complètement fonctionnelle.

La solution utilisée pour les métadonnées est fournie par le composant ThomasRuleEngine. L'algorithme implémente la solution du "Last Writter Win", sachant que dans le cas de l'architecture de l'application XWoot, la solution réellement implantée est plutôt un "Last Synchronizer Win" (les métadonnées n'ont d'existence pour le ThomasRuleEngine que lorsqu'elles ont été synchronisées : les métadonnées ne sont décorée par le modèle du ThomasRuleEngine qu'à ce moment là). Ainsi, entre le moment de la dernière synchronisation sur l'ensemble du réseau et l'application du patch en résultant, toute les modifications effectuées sur les vues, mais non synchronisées, sont écrasées.

\paragraph{Entrées du composant}

\begin{itemize}
\item L'ensemble des méthodes de gestion des pages à synchoriser (addPageManagement, addAllPageManagement, removeManagedPage, removeAllManagedPage,isPageManaged).
\item Le constructeur qui reçoit les instances des composants à utiliser.
\item setState : charger un état donné.
\end{itemize}

\paragraph{Sorties du composant}

\begin{itemize}
\item doAntiEntropy : effectuer une anti-entropie avec un voisin.
\item synchronize : lancer une synchronisation vue/modèle.
\item receive : appliquer un patch au modèle.
\item getState : récupérer l'état du modèle courant.
\end{itemize}

\paragraph{Diagramme de classe}


\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{figures/XWoot_class.jpg}
  \caption{Diagramme de classe du composant XWoot}
  \label{fig:xwoot-class}
\end{figure}


\subsubsection{AntiEntropy}

Ce composant permet de gérer l'ensemble des opérations nécessaires à l'application d'une anti-entropie entre deux sites.

\paragraph{La déconnexion}

En complément du LPBCast, ce module permet la gestion du mode déconnecté.
En effet, lorsqu’un nœud se déconnecte du réseau, il n’est plus mis à jour par les modifications arrivant après sa déconnexion. Lorsqu’il se reconnecte, afin d’éviter de faire diverger les données répliquées, le nœud doit récupérer et appliquer l’ensemble des patchs qu’il n’a pas reçu durant sa déconnexion.

\paragraph{Le log}

Lorsque le module LPBCast reçoit un message et que celui-ci est appliqué, il le log dans le module d’anti-entropie ; le module possède donc l’ensemble des messages que le nœud a reçus et appliqués. Le log est sérialisé dans un fichier.

\paragraph{L'anti-entropie}

Pour qu'un nœud récupère l'ensemble des patchs qu'il n'a pas reçu durant sa déconnexion, il doit lancer une anti-entropie avec un de ses voisins. Pour ce faire, il doit envoyer un message de demande d’anti-entropie contenant l’ensemble des patchs de son log. Le voisin recevant la demande, doit alors renvoyé la différence des patchs qu’il  contient dans son log. Le demandeur n’a plus qu’à appliquer un par un les patchs qu’il reçoit en retour de sa demande.

\paragraph{Diagramme de composant}

\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{figures/AntiEntropyComponent.jpg}
  \caption{Diagramme composant Anti-entropy}
  \label{fig:antientropy}
\end{figure}


Remarque : le composant AntiEntropy contient un composant interne de log, qu’il est donc le seul à utiliser.

\paragraph{Entrées}

\begin{itemize}
\item AntiEntropy
\begin{itemize}
\item logMessage : permet d’ajouter un message dans le log
\end{itemize}
\item Log
\begin{itemize}
\item addMessage : permet d'ajouter un message dans le log
\end{itemize}
\end{itemize}

\paragraph{Sorties}

\begin{itemize}
\item{AntiEntropy}
\begin{itemize}
\item answerAntiEntropy : permet de récupérer la différence entre un tableau de patch donné et le log
\item getContentForAskAntiEntropy : permet de récupérer un tableau contenant les identifiants des messages contenus dans le log
\item getLog : retourne le log
\end{itemize}
\item Log
\begin{itemize}
\item logSize : permet de récupérer le nombre d’éléments sotckés dans le log
\item getMessage : permet de récupérer un message dans le log en fonction de son identifiant
\item getMessagesId : permet de récupérer la liste des identifiants des patchs stockés dans le log.
\item existInLog : permet de savoir si un message d’identifiant donné est dans le log
\item getDiffKey : permet de récupérer le tableau de la différence entre les entrées du log et un tableau d'identifiant donné.
\item getAllEntries : retourne le tableau des entrées contenues dans le log
\end{itemize}
\end{itemize}

\paragraph{Diagramme de classe}

\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{figures/AntiENtropy_class.jpg}
  \caption{Diagramme de classe du composant Anti-entropy}
  \label{fig:antientropy-class}
\end{figure}

\section{Adaptation aux terminaux mobiles - skin iPhone}

La skin iPhone a été écrite "à partir de zéro", en s'appuyant sur le code
des skins \textit{albatross} et \textit{dodo} d'XWiki. Ceci a permis d'obtenir
un modèle plus propre, d'autant plus qu'XWiki offre cet avantage de se
replier sur les composants de la skin \textit{albatross} lorsqu'il ne le
trouve pas dans la skin courante, ce qui offre une certaine souplesse.

Elle fait usage de la bibliothèque iUI de Joe Hewitt (le développeur de
la version iPhone de facebook) qui propose des fonctionnalités
particulièrement adaptées à l'environnement d'un iPhone ou d'un iPod
touch. Cette bibliothèque CSS+Javascript propose normalement une
navigation fondée sur le chargement dynamique de pages par Ajax, qui
permet de ne charger que la partie de la page qui est différente.
Cependant, ne souhaitant intervenir que sur l'affichage et non modifier
le cœur de l'application, nous avons renoncé à modifier les liens
produits en fonction du contexte, et n'avons donc pas utilisé cette
fonctionnalité, et il a donc fallu altérer légèrement le code de la
bibliothèque JavaScript d'iUI. Le code CSS a lui aussi été modifié de
façon notamment à introduire une barre de menus en-dessous de la barre
de titre. 

Le code html d'une page destinée à utiliser iUI est constitué d'une
succession de \textit{div} décrivant chacun un élément de l'interface : 

\paragraph{Barre de titre} La barre de titre est décrite par une
\textit{div} de classes \textit{toolbar} et \textit{titlebar}. Le titre
lui-même est balisé par un \textit{h1} tandis que deux emplacements
(l'un à gauche, l'autre à droite) sont prévus pour accueillir des
boutons décrits par une balise \textit{a} de classe \textit{button}. 

\begin{lstlisting}[frame=single, float=p, caption=Barre de titre,
captionpos=b]
    <div class="toolbar titlebar">
        <h1 id="pageTitle"><a href="/xwiki/bin/view/Main/"
target="_self">XWiki</a></h1>
        <a id="backButton" class="button"
href="javascript:history.go(-1)"></a>

        <a class="button" href="#subMenu">Actions</a>
    </div>
\end{lstlisting}


\paragraph{Boîte de dialogue} Il est possible de faire apparaître une
boîte de dialogue qui se déroule à partir de la barre de titre au-dessus
du contenu principal lorsqu'on clique sur un bouton ou un lien. Pour
cela, le contenu doit être placé dans un contexte \textit{form} de
classe \textit{dialog}. Le titre de la boîte de dialogue remplace alors
le titre de la page, et il en est de même pour d'éventuels boutons. Ces
éléments sont décrits de la même façon que pour la barre de titre. 

\begin{lstlisting}[frame=single, float=p, caption=Boîte de dialogue,
captionpos=b]
    <form id="searchForm" class="dialog"
action="/xwiki/bin/view/Main/WebSearch" target="_self">
        <fieldset>
            <h1>Rechercher</h1>
            <a class="button leftButton" type="cancel">Annuler</a>
            <input type="text" name="text"/>
            <input type="submit" />
        </fieldset>
    </form>
\end{lstlisting}


\paragraph{Barre de menus} La barre de menus est un élément décrit par
une \textit{div} de classes \textit{toolbar} et \textit{menubar}. Il
contient de la place pour quatre éléments, chacun étant codé comme un
lien. 

\begin{lstlisting}[frame=single, float=p, caption=Barre de menus,
captionpos=b]
    <div class="menubar toolbar">
        <a href="/xwiki/bin/edit/Main/WebHome">Editer</a>
        <a href="/xwiki/bin/view/Main/?viewer=history">Historique</a>
        <a href="/xwiki/bin/view/Main/?viewer=comments">Commentaires
(0)</a>
        <a href="more">Avanc'e</a>
    </div>
\end{lstlisting}


\paragraph{Contenu principal} Le contenu principal est repéré par une
\textit{div} marquée comme active par l'attribut \textit{selected}. Il
est affiché comme du contenu html standard et toutes les libertés sont
possibles à l'intérieur de cet élément. 

\begin{lstlisting}[frame=single, float=p, caption=Barre de titre,
captionpos=b]
  <div selected="true">
    <div class="main-content">
        <h2 class="heading-1">Welcome to your wiki</h2>
Welcome to the wiki administrator of your wiki farm! It is a space that
will allow you to create as wiki as you want and manage it. Each wiki
you will create is a shared workspace that will allow you to collaborate
effectively with others. You will be able to use it for many purposes:

<ul class="star">
<li>Project Management</li>
<li>Collaborative Writing</li>
<li>Efficient Document Sharing</li>
<li>Knowledge Management</li>
</ul>

For more information you can visit the documentation on xwiki.org.<p
class="paragraph"/>
This XWiki is yours, we hope you'll enjoy it ...<p class="paragraph"/>
Congratulations,
The XWiki Team
    </div>
  </div>
\end{lstlisting}


\paragraph{Contenu annexe} Enfin, il est possible de prévoir un contenu
alternatif qui s'affichera en lieu et place du contenu principal
lorsqu'un lien portant une ancre nommée sera cliqué. Le nom de cette
ancre doit correspondre à l'attribut \textit{id} de la \textit{div}. 

\begin{lstlisting}[frame=single, float=p, caption=Barre de titre,
captionpos=b]
    <div id="more" class="panel">
	<ul>
<li id="xwikieditobject"><a
href="/xwiki/bin/edit/Main/WebHome?editor=object&amp;">Objets</a></li> 
<li id="xwikieditclass"><a
href="/xwiki/bin/edit/Main/WebHome?editor=class&amp;">Classe</a></li> 
<li id="xwikieditrights"><a
href="/xwiki/bin/edit/Main/WebHome?editor=rights&amp;">Droits
d'Acc`es</a></li>
<li id="xwikiedithistory"><a
href="/xwiki/bin/edit/Main/WebHome?editor=history&amp;&amp;">Historique</a></li>
	</ul>
    </div>
\end{lstlisting}


\section{XWiki Eclipse}

Le client XWiki Eclipse permet de se connecter à un ou plusieurs wikis distants, puis à travailler en mode déconnecté sur les contenus rappatriés, et à synchroniser les changements effectués avec les versions distantes. Le couplage avec les composants XWoot et SB-KTS sera effectué dans la deuxième phase du projet.

Les instructions d'installation de XWiki Eclipse sont disponibles directement en ligne à l'adresse suivante: \url{http://code.xwiki.org/xwiki/bin/view/Extensions/XEclipseExtension}.

